package licode.unisop.client.service.impl;

import licode.unisop.client.api.AuthCallback;
import licode.unisop.client.api.SopPlatform;
import licode.unisop.client.api.SopPlatformAuth;
import licode.unisop.client.api.SopUriFilter;
import licode.unisop.client.api.auth.SopResourceQuery;
import licode.unisop.client.info.*;
import licode.unisop.client.utils.SopRequestParse;
import licode.unisop.client.vo.SopAuthPlatform;
import licode.unisop.client.vo.SopUrl;
import licode.unisop.client.vo.SopVerifyCode;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;

@Service
@Scope("prototype")
class SopClientPlatformImpl implements SopPlatform {
    @Resource
    private SopResourceQuery resourceQuery;

    @Resource
    private SopPlatformAuth sopPlatformAuth;

    private SopPlatAuthInfo authInfo;
    private SopUriFilter sopUriFilter;
    private AuthCallback authCallback;

    private SopAuthPlatform sopAuthPlatform = new SopAuthPlatform();

    private HttpServletRequest request() {
        ServletRequestAttributes attributes;
        attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        return null == attributes ? null : attributes.getRequest();
    }

    private SopTokenInfo getAuthToken() {
        return SopRequestParse.getAccessTokenInfo(request());
    }

    @Override
    public String getModalToken() {
        return sopAuthPlatform.getModelToken();
    }

    @Override
    public SopUriFilter getUriFilter() {
        return sopUriFilter;
    }

    @Override
    public void registerUriFilter(SopUriFilter sopUriFilter) {
        this.sopUriFilter = sopUriFilter;
    }

    @Override
    public AuthCallback getAuthCallback() {
        return authCallback;
    }

    @Override
    public void registerAuthCallback(AuthCallback authCallback) {
        this.authCallback = authCallback;
    }

    private SopTokenInfo checkAccessToken() {
        SopTokenInfo token = getAuthToken();
        token.setPlatformId(sopAuthPlatform.getPlatformId());
        return token;
    }

    @Override
    public boolean isValid() {
        return !sopAuthPlatform.isValid();
    }

    @Override
    public void updateAuthInfo(SopAuthPlatform authPlat) {
        if (null == authPlat) {
            sopAuthPlatform.setToken("");
            sopAuthPlatform.setModelToken("");
            sopAuthPlatform.setTicketUrl("");
            sopAuthPlatform.setInnerToken("");
        } else {
            sopAuthPlatform.setToken(authPlat.getToken());
            sopAuthPlatform.setModelToken(authPlat.getModelToken());
            sopAuthPlatform.setTicketUrl(authPlat.getTicketUrl());
            sopAuthPlatform.setInnerToken(authPlat.getInnerToken());
        }
    }

    @Override
    public SopAuthPlatform getAuthPlatform() {
        return sopAuthPlatform.clonePl();
    }

    @Override
    public SopAuthPlatform auth(SopPlatAuthInfo authInfo) {
        sopAuthPlatform = sopPlatformAuth.register(authInfo);
        if (null == sopAuthPlatform) {
            sopAuthPlatform = new SopAuthPlatform();
        }
        this.authInfo = authInfo;
        return getAuthPlatform();
    }

    @Override
    public String getId() {
        return authInfo.getId();
    }

    @Override
    public String getRealmId() {
        return authInfo.getRealmId();
    }

    @Override
    public String getName() {
        if (sopAuthPlatform != null) {
            return sopAuthPlatform.getName();
        }
        return "";
    }

    @Override
    public String getToken() {
        return sopAuthPlatform.getToken();
    }

    @Override
    public String getTicketUri() {
        return sopAuthPlatform.getTicketUrl();
    }

    @Override
    public int matchUri(String url) {
        return resourceQuery.ssoMatchUrl(SopUrlInfo.builder()
                .info(checkAccessToken())
                .url(url)
                .build()).flag();
    }

    @Override
    public SopVerifyCode hasRole(SiRoleAction info) {
        return resourceQuery.hasRole(SopRoleInfo.builder()
                .info(checkAccessToken())
                .action(info)
                .build());
    }

    @Override
    public SopVerifyCode hasPermit(SiPermitAction info) {
        return resourceQuery.hasPermit(SopPermitInfo.builder()
                .info(checkAccessToken())
                .action(info)
                .build());
    }

    @Override
    public SopVerifyCode hasAuthority(SiAuthorityAction info) {
        return resourceQuery.hasAuthority(SopAuthorityIn.builder()
                .info(checkAccessToken())
                .action(info)
                .build());
    }
}
